#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
线性度计算示例 - 基于电流探头200μs数据 (简化版)
"""

def calculate_linearity_simple(x_data, y_data, method_name):
    """
    计算线性度(R²值) - 简化版本
    """
    
    n = len(x_data)
    
    # 计算平均值
    x_mean = sum(x_data) / n
    y_mean = sum(y_data) / n
    
    # 计算线性回归系数
    # 斜率 a = Σ(x-x̄)(y-ȳ) / Σ(x-x̄)²
    # 截距 b = ȳ - a*x̄
    
    numerator = 0
    denominator = 0
    
    for i in range(n):
        numerator += (x_data[i] - x_mean) * (y_data[i] - y_mean)
        denominator += (x_data[i] - x_mean) ** 2
    
    slope = numerator / denominator
    intercept = y_mean - slope * x_mean
    
    # 计算预测值
    y_pred = [slope * x_data[i] + intercept for i in range(n)]
    
    # 计算残差
    residuals = [y_data[i] - y_pred[i] for i in range(n)]
    
    # 计算SS_res和SS_tot
    ss_res = sum([residuals[i] ** 2 for i in range(n)])
    ss_tot = sum([(y_data[i] - y_mean) ** 2 for i in range(n)])
    
    # 计算R²
    r2 = 1 - (ss_res / ss_tot)
    
    # 计算平均绝对误差
    mae = sum([abs(residuals[i]) for i in range(n)]) / n
    
    # 计算最大偏差
    max_deviation = max([abs(residuals[i]) for i in range(n)])
    
    print(f"\n=== {method_name} 线性度分析 ===")
    print(f"线性回归方程: y = {slope:.4f}x + {intercept:.4f}")
    print(f"决定系数(R²): {r2:.6f}")
    print(f"平均绝对误差: {mae:.4f}A")
    print(f"最大偏差: {max_deviation:.4f}A")
    
    return r2, slope, intercept, y_pred, residuals, ss_res, ss_tot

def main():
    # 电流探头200μs数据 (大灯丝模式)
    gui_setting = [0, 0.5, 1, 1.5, 2, 2.5, 3, 3.5, 4, 4.5, 5, 5.5]
    current_probe_200us = [0.169, 0.572, 1.018, 1.576, 2.068, 2.568, 3.061, 3.551, 4.117, 4.592, 4.948, 5.363]
    
    # 电流探头20μs数据 (大灯丝模式)
    current_probe_20us = [0.172, 0.614, 1.085, 1.654, 2.154, 2.663, 3.167, 3.664, 4.234, 4.696, 5.067, 5.471]
    
    # DMM6500电压/电阻数据 (大灯丝模式)
    dmm6500_voltage = [0.2435, 1.0508, 1.7150, 2.3870, 2.8569, 3.3386, 3.8381, 4.3546, 4.8141, 5.3121, 5.8377, 6.3961]
    
    print("=" * 60)
    print("线性度计算详细分析")
    print("=" * 60)
    
    # 计算各方法的线性度
    r2_200us, slope_200us, intercept_200us, pred_200us, res_200us, ss_res_200us, ss_tot_200us = calculate_linearity_simple(
        gui_setting, current_probe_200us, "电流探头200μs"
    )
    
    r2_20us, slope_20us, intercept_20us, pred_20us, res_20us, ss_res_20us, ss_tot_20us = calculate_linearity_simple(
        gui_setting, current_probe_20us, "电流探头20μs"
    )
    
    r2_dmm, slope_dmm, intercept_dmm, pred_dmm, res_dmm, ss_res_dmm, ss_tot_dmm = calculate_linearity_simple(
        gui_setting, dmm6500_voltage, "DMM6500电压/电阻"
    )
    
    # 创建对比表格
    print(f"\n=== 线性度对比总结 ===")
    print(f"{'测量方法':<20} {'R²值':<10} {'线性度评价':<15}")
    print("-" * 50)
    print(f"{'电流探头200μs':<20} {r2_200us:<10.6f} {'优秀' if r2_200us > 0.99 else '良好' if r2_200us > 0.95 else '一般':<15}")
    print(f"{'电流探头20μs':<20} {r2_20us:<10.6f} {'优秀' if r2_20us > 0.99 else '良好' if r2_20us > 0.95 else '一般':<15}")
    print(f"{'DMM6500电压/电阻':<20} {r2_dmm:<10.6f} {'优秀' if r2_dmm > 0.99 else '良好' if r2_dmm > 0.95 else '一般':<15}")
    
    # 详细计算过程展示 (以电流探头200μs为例)
    print(f"\n=== 电流探头200μs 详细计算过程 ===")
    print(f"{'GUI设定':<8} {'实际测量':<10} {'预测值':<10} {'残差':<10} {'残差²':<10}")
    print("-" * 50)
    
    for i in range(len(gui_setting)):
        residual = res_200us[i]
        residual_sq = residual ** 2
        print(f"{gui_setting[i]:<8.1f} {current_probe_200us[i]:<10.3f} {pred_200us[i]:<10.3f} {residual:<10.3f} {residual_sq:<10.6f}")
    
    print(f"\n详细计算:")
    print(f"SS_res (残差平方和) = {ss_res_200us:.6f}")
    print(f"SS_tot (总平方和) = {ss_tot_200us:.6f}")
    print(f"R² = 1 - (SS_res/SS_tot) = 1 - ({ss_res_200us:.6f}/{ss_tot_200us:.6f}) = {1 - ss_res_200us/ss_tot_200us:.6f}")
    
    # 线性度评价标准
    print(f"\n=== 线性度评价标准 ===")
    print("R² > 0.99: 优秀 (线性度极好)")
    print("0.95 < R² ≤ 0.99: 良好 (线性度较好)")
    print("0.90 < R² ≤ 0.95: 一般 (线性度可接受)")
    print("R² ≤ 0.90: 较差 (线性度不佳)")
    
    # 实际应用意义
    print(f"\n=== 线性度在实际应用中的意义 ===")
    print("1. R²值越接近1，说明测量值与设定值之间的线性关系越好")
    print("2. 线性度好的测量方法，可以用于精确的校准和标定")
    print("3. 从计算结果看，电流探头200μs的线性度最好(R²=0.999)，")
    print("   适合作为校准基准使用")
    print("4. DMM6500电压/电阻方法虽然线性度也很好(R²=0.999)，")
    print("   但由于灯丝电阻受热变化，实际测量精度较差")

if __name__ == "__main__":
    main()
